home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc Development Framework / ODFDev / ODF / OS / FWFiles / Sources / FWFilPar.cpp < prev    next >
Encoding:
Text File  |  1995-11-08  |  18.7 KB  |  671 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:        FWFilPar.cpp
  4. //    Release Version:    $ 1.0d11 $
  5. //
  6. //    Copyright:    1995 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWOS.hpp"
  11.  
  12. #ifndef FWFILPAR_H
  13. #include "FWFilPar.h"
  14. #endif
  15.  
  16. #ifndef FWFILESP_H
  17. #include "FWFileSp.h"
  18. #endif
  19.  
  20. #ifndef FWFILESY_H
  21. #include "FWFileSy.h"
  22. #endif
  23.  
  24. #ifndef FWSTRTOO_H
  25. #include "FWStrToo.h"
  26. #endif
  27.  
  28. #ifndef FWBNDSTR_H
  29. #include "FWBndStr.h"
  30. #endif
  31.  
  32. #ifndef FWEXCDEF_H
  33. #include "FWExcDef.h"
  34. #endif
  35.  
  36. #if defined(FW_BUILD_WIN) && !defined(FWMEMMGR_H)
  37. #include "FWMemMgr.h"
  38. #endif
  39.  
  40. #if defined(FW_BUILD_WIN) && !defined(__DOS_H)
  41. #include <dos.h>
  42. #endif
  43.  
  44. #if defined(FW_BUILD_WIN) && !defined(__DIRECT_H)
  45. #include <direct.h>
  46. #endif
  47.  
  48. #if defined(FW_BUILD_WIN) && !defined(__IO_H)
  49. #include <io.h>
  50. #endif
  51.  
  52. #if FW_LIB_EXPORT_PRAGMAS
  53. #pragma lib_export on
  54. #endif
  55.  
  56. #ifdef FW_BUILD_WIN16
  57. extern "C" void FAR PASCAL DOS3Call();                // We don't do "int 21h" under Windows
  58. #endif
  59.  
  60.  
  61. //========================================================================================
  62. // CLASS FW_CPrivFileSystemParser
  63. //========================================================================================
  64.  
  65. //----------------------------------------------------------------------------------------
  66. //    FW_CPrivFileSystemParser::IsPartialPath
  67. //
  68. //    Return TRUE if pathName specifies a partial pathName.
  69. //
  70. //  On Windows, only a fully qualified pathname will return FALSE.  That is a path that
  71. //    specifies a drive and directory starting from the root directory of the drive.
  72. //  On Mac, a partial pathname is any string that starts with a path separator character.
  73. //----------------------------------------------------------------------------------------
  74.  
  75. FW_Boolean FW_CPrivFileSystemParser::IsPartialPath(const FW_CString& pathName) 
  76. {
  77.     FW_Boolean result = TRUE;
  78.  
  79. #ifdef FW_BUILD_WIN
  80.     if (pathName.GetLength() > 0)
  81.     {
  82.         FW_CString32 drivePathSeparator(&FW_kDriveDelimiter, 1);
  83.         FW_CharacterPosition drivePosition;
  84.         
  85.         drivePathSeparator += FW_kPathDelimiter;
  86.         
  87.         if (pathName.FindSubString(drivePathSeparator, drivePosition))
  88.             result = FALSE;
  89.     }
  90. #endif
  91.  
  92. #ifdef FW_BUILD_MAC
  93.     if (pathName.GetLength() > 0)
  94.         result = (pathName[0] == FW_kPathDelimiter);
  95. #endif
  96.  
  97.     return (result);
  98. }
  99.  
  100.  
  101. //----------------------------------------------------------------------------------------
  102. //    FW_CPrivFileSystemParser::AddDelimiter
  103. //
  104. //  Adds a trailing backslash if appropriate.  It will not add a delimiter if one already
  105. //    exists, the path length is zero (indicating the default directory),or if the last 
  106. //    character is a colon (indicating a drive name).
  107. //----------------------------------------------------------------------------------------
  108.  
  109. void FW_CPrivFileSystemParser::AddDelimiter(FW_CString& pathName) 
  110. {
  111.     FW_CharacterPosition lastCharacter;
  112.  
  113.     lastCharacter = pathName.GetLength() - 1;
  114.  
  115.     if (lastCharacter >= 0)
  116.     {
  117. #ifdef FW_BUILD_WIN
  118.         if ((pathName[lastCharacter] != FW_kPathDelimiter) && (pathName[lastCharacter] != FW_kDriveDelimiter))
  119.             pathName += FW_kPathDelimiter;
  120. #endif
  121.  
  122. #ifdef FW_BUILD_MAC
  123.         if (pathName[lastCharacter] != FW_kPathDelimiter)
  124.             pathName += FW_kPathDelimiter;
  125. #endif
  126.  
  127.     }
  128. }
  129.  
  130.  
  131. #ifdef FW_BUILD_WIN16
  132. //----------------------------------------------------------------------------------------
  133. // PrivPrimitiveGetDefaultDrive
  134. //
  135. //  Return the current default drive number where A=0, B=1, C=2, etc.
  136. //----------------------------------------------------------------------------------------
  137. short FW_CPrivFileSystemParser::PrivPrimitiveGetDefaultDrive()
  138. {
  139.     short driveNumber = -1;
  140.     
  141.     __asm {
  142.         mov        ah, 19h
  143.     }
  144.     
  145.     DOS3Call();
  146.     
  147.     __asm {
  148.         mov        driveNumber, ax
  149.     }
  150.     
  151.     return (driveNumber);
  152. }
  153. #endif
  154.  
  155.  
  156. #ifdef FW_BUILD_WIN16
  157. //----------------------------------------------------------------------------------------
  158. // PrivPrimitiveGetCurrentDir
  159. //
  160. //  namePtr is a pointer to a buffer.  On return, this buffer will contain the directory
  161. //    name.  This buffer should be at least 64 bytes long.
  162. //  Returns an error code.
  163. //----------------------------------------------------------------------------------------
  164. short FW_CPrivFileSystemParser::PrivPrimitiveGetCurrentDir(FW_Char* namePtr)
  165. {
  166.     FW_CFileSystem::FileError theError = FW_CFileSystem::kNoError;
  167.     
  168.     __asm {
  169.         push    ds
  170.         lds        si, [namePtr]
  171.         mov        dl, 00h
  172.         mov     ah, 47h
  173.     }
  174.     
  175.     DOS3Call();
  176.         
  177.     __asm {
  178.         pop     ds
  179.         jc        _error
  180.         xor     ax, ax
  181.     }
  182.             
  183.     _error:
  184.     
  185.     __asm {
  186.         mov        theError, ax
  187.     }
  188.     
  189.     return (theError);
  190. }
  191. #endif
  192.  
  193.  
  194. //----------------------------------------------------------------------------------------
  195. // FW_CPrivFileSystemParser::PrivGetWorkingDirectory
  196. //----------------------------------------------------------------------------------------
  197.  
  198. short FW_CPrivFileSystemParser::PrivGetWorkingDirectory(FW_CString& directoryName)
  199. {
  200.     FW_CFileSystem::FileError theError = FW_CFileSystem::kNoError;
  201.     
  202.     directoryName = "";
  203.  
  204. #ifdef FW_BUILD_WIN16
  205.     FW_CString255 buffer;
  206.     const FW_Char* namePtr = (const FW_Char*)buffer;
  207.     short driveNumber = PrivPrimitiveGetDefaultDrive();
  208.     
  209.     directoryName = "";
  210.     directoryName += (FW_Char)(driveNumber + 'a');
  211.     directoryName += FW_kDriveDelimiter;
  212.     directoryName += FW_kPathDelimiter;
  213.     
  214.     theError = PrivPrimitiveGetCurrentDir((FW_Char*)namePtr);
  215.     if (theError == FW_CFileSystem::kNoError)
  216.         directoryName += namePtr;
  217. #endif
  218.  
  219. #ifdef FW_BUILD_WIN32
  220.     char* dirBuffer = new char[MAX_PATH];
  221.     long dirNameLength = ::GetCurrentDirectory(MAX_PATH, dirBuffer);
  222.     
  223.     if(dirNameLength == 0)
  224.         theError = ::GetLastError();
  225.     else
  226.         directoryName = dirBuffer;
  227.  
  228.     delete [] dirBuffer;
  229. #endif
  230.  
  231.  
  232. #ifdef FW_BUILD_MAC
  233.     short vRefNum;
  234.     long dirID;
  235.         
  236.     theError = ::HGetVol(NULL, &vRefNum, &dirID);
  237.     
  238.     if (theError == FW_CFileSystem::kNoError)
  239.         theError = MacGenerateFullPathName(vRefNum, dirID, directoryName);
  240.     
  241. #endif
  242.     return (theError);
  243. }
  244.  
  245.  
  246. //----------------------------------------------------------------------------------------
  247. //    FW_CPrivFileSystemParser::HasExtension
  248. //
  249. //  Return TRUE if the file name has a dot-extension.  Return the dot position in the
  250. //    dotPosition parameter.
  251. //    This routine searches the string backwards for the first path delimiter it sees.  
  252. //    It then searches the routine forwards searching for the first period it sees.
  253. //    It returns TRUE if it finds the period.
  254. //----------------------------------------------------------------------------------------
  255.  
  256. FW_Boolean FW_CPrivFileSystemParser::HasExtension(const FW_CString& fileName,
  257.                                                     FW_CharacterPosition& dotPosition) 
  258. {
  259.     FW_Boolean result = FALSE;
  260.     FW_CharacterPosition pathDelimiterPosition;
  261.  
  262.     dotPosition = 0;
  263.  
  264.     if (fileName.GetLength() > 0)
  265.     {
  266.         FW_CStringTool *tool = FW_CStringTool::GetCurrentStringTool();
  267.         result = tool->FindCharacter(fileName, FW_kPathDelimiter, pathDelimiterPosition, fileName.GetLength() - 1, FW_kBackwards);
  268.         if (!result)
  269.             pathDelimiterPosition = -1;
  270.  
  271.         result = tool->FindCharacter(fileName, FW_kExtensionDelimiter, dotPosition, pathDelimiterPosition + 1, FW_kForwards);
  272.     }
  273.  
  274.     return (result);
  275. }
  276.  
  277.  
  278. //----------------------------------------------------------------------------------------
  279. //    FW_CPrivFileSystemParser::ChangeExtension
  280. //
  281. //  Return a pathname with the specified extension attached.  fileName can be a full or
  282. //    partial pathname.  If an extension already exists, it will be overwritten.
  283. //----------------------------------------------------------------------------------------
  284.  
  285. void FW_CPrivFileSystemParser::ChangeExtension(const FW_CString& pathName,
  286.                                                  const FW_CString& extension,
  287.                                                  FW_CString& returnName) 
  288. {
  289.     FW_CharacterPosition dotPosition;
  290.  
  291.     returnName = pathName;
  292.  
  293.     // If there is already an extension, trancate it and the dot.
  294.     if (HasExtension(pathName, dotPosition))
  295.         returnName.Truncate(dotPosition);
  296.  
  297.     returnName += FW_kExtensionDelimiter;
  298.     returnName += extension;
  299. }
  300.  
  301.  
  302. //----------------------------------------------------------------------------------------
  303. //    FW_CPrivFileSystemParser::GetExtension
  304. //
  305. //  Return the extension to this file in extension.  If no extension exists, then FALSE
  306. //    is returned, otherwise TRUE is returned.
  307. //----------------------------------------------------------------------------------------
  308.  
  309. FW_Boolean FW_CPrivFileSystemParser::GetExtension(const FW_CString& pathName,
  310.                                                     FW_CString& extension) 
  311. {
  312.     FW_CharacterPosition dotPosition;
  313.     FW_Boolean result = FALSE;
  314.  
  315.     extension = "";
  316.  
  317.     // Delete everything before the extension, including the dot.
  318.     if (HasExtension(pathName, dotPosition))
  319.     {
  320.         FW_Char charToAdd;
  321.  
  322.         FW_CStringReader reader(pathName);
  323.         reader.SetPosition(dotPosition + 1);
  324.  
  325.         while ((charToAdd = reader.GetCharacterAndAdvance()) != FW_kNulCharacter)
  326.             extension += charToAdd;
  327.  
  328.         result = TRUE;
  329.     }
  330.  
  331.     return (result);
  332. }
  333.  
  334.  
  335. //----------------------------------------------------------------------------------------
  336. //    FW_CPrivFileSystemParser::GetFileName
  337. //
  338. //  Return the filename portion without any path information.  The filename includes
  339. //    the file extension.  
  340. //----------------------------------------------------------------------------------------
  341.  
  342. FW_Boolean FW_CPrivFileSystemParser::GetFileName(const FW_CString& pathName,
  343.                                                    FW_CString& fileName) 
  344. {
  345.     FW_CharacterPosition delimiterPosition;
  346.     FW_Boolean result = FALSE;
  347.  
  348.     fileName = "";
  349.     
  350.     if (pathName.GetLength() > 0)
  351.     {
  352.         FW_CStringTool *tool = FW_CStringTool::GetCurrentStringTool();
  353.         result = tool->FindCharacter(pathName, FW_kPathDelimiter, delimiterPosition, pathName.GetLength() - 1, FW_kBackwards);
  354.  
  355. #ifdef FW_BUILD_WIN
  356.         // Only needed for Windows since path and drive delimiters are different.
  357.         if (!result)
  358.             result = tool->FindCharacter(pathName, FW_kDriveDelimiter, delimiterPosition, pathName.GetLength() - 1, FW_kBackwards);
  359. #endif
  360.  
  361.         if (result)
  362.         {
  363.             FW_CStringReader reader(pathName);
  364.             reader.SetPosition(delimiterPosition + 1);
  365.  
  366.             FW_Char charToAdd;
  367.             while ((charToAdd = reader.GetCharacterAndAdvance()) != FW_kNulCharacter)
  368.                 fileName += charToAdd;
  369.         }
  370.     }
  371.     else
  372.         fileName = "";
  373.  
  374.     return (result);
  375. }
  376.  
  377.  
  378. //----------------------------------------------------------------------------------------
  379. //    FW_CPrivFileSystemParser::GetJustFileName
  380. //
  381. //  Get the full file name and truncate off the dot and extension.
  382. //----------------------------------------------------------------------------------------
  383.  
  384. FW_Boolean FW_CPrivFileSystemParser::GetJustFileName(const FW_CString& pathName,
  385.                                                        FW_CString& fileName) 
  386. {
  387.     FW_CharacterPosition dotPosition;
  388.  
  389.     FW_Boolean result = GetFileName(pathName, fileName);
  390.  
  391.     if (HasExtension(fileName, dotPosition))
  392.         fileName.Truncate(dotPosition);
  393.  
  394.     return (result);
  395. }
  396.  
  397.  
  398.  
  399.  
  400. //===========================================
  401. // Windows Routines
  402. //===========================================
  403.  
  404. #ifdef FW_BUILD_WIN
  405. //----------------------------------------------------------------------------------------
  406. //    FW_CPrivFileSystemParser::WinGetPathName
  407. //
  408. //  Returns the directory information in pathName.  If the directory is anything but a root
  409. //    directory, then there is no trailing backslash on the end of the path.  This makes
  410. //    it easier to create FW_CDirectorySpecification's.
  411. //  Returns FALSE if there is no path information, otherwise returns TRUE to indicate some
  412. //    path information was present.  The information that gets returned may still be part
  413. //    of a partial pathname.
  414. //----------------------------------------------------------------------------------------
  415.  
  416. FW_Boolean FW_CPrivFileSystemParser::WinGetPathName(const FW_CString& fullPathName,
  417.                                                    FW_CString& pathName) 
  418. {
  419.     FW_CharacterPosition backSlashPosition = 0;
  420.     FW_CharacterPosition colonPosition = 0;
  421.     FW_CharacterPosition delimiterPosition;
  422.  
  423.     FW_Boolean backSlashResult = FALSE;
  424.     FW_Boolean colonResult = FALSE;
  425.     FW_Boolean functionResult = FALSE;
  426.  
  427.     pathName = "";
  428.  
  429.     if (fullPathName.GetLength() > 0)
  430.     {
  431.         // Search backwards for the first character in the delimiter set of '\' and ':'.
  432.         FW_CStringTool *tool = FW_CStringTool::GetCurrentStringTool();
  433.  
  434.         backSlashResult = tool->FindCharacter(fullPathName, FW_kPathDelimiter, backSlashPosition, fullPathName.GetLength() - 1, FW_kBackwards);
  435.         colonResult = tool->FindCharacter(fullPathName, FW_kDriveDelimiter, colonPosition, fullPathName.GetLength() - 1, FW_kBackwards);
  436.  
  437.         delimiterPosition = FW_Maximum(backSlashPosition, colonPosition);
  438.  
  439.         // If no delimiters were found, then there is no path information here. 
  440.         // Else return what path information there was.
  441.  
  442.         if (backSlashResult || colonResult)
  443.         {
  444.             if (delimiterPosition == 0)
  445.                 pathName += fullPathName[delimiterPosition];
  446.             else
  447.             {
  448.                 pathName = fullPathName;
  449.  
  450.                 if (fullPathName[delimiterPosition] == FW_kPathDelimiter)
  451.                 {
  452.                     // If the directory is the root directory, leave the trailing backslash.
  453.                     //   Otherwise remove it.
  454.                     if (fullPathName[(FW_CharacterPosition)(delimiterPosition - 1)] == FW_kDriveDelimiter)
  455.                         pathName.Truncate(delimiterPosition + 1);
  456.                     else
  457.                         pathName.Truncate(delimiterPosition);
  458.                 }
  459.                 else
  460.                     pathName.Truncate(delimiterPosition + 1);
  461.             }
  462.  
  463.             functionResult = TRUE;
  464.         }
  465.     }
  466.  
  467.     return (functionResult);
  468. }
  469. #endif
  470.  
  471.  
  472. #ifdef FW_BUILD_WIN
  473. //----------------------------------------------------------------------------------------
  474. //    FW_CPrivFileSystemParser::WinGetDrivePath
  475. //
  476. //  Returns the drive letter and colon character in drivePath if a drive was specified.
  477. //    If no drive was specified, then FALSE is returned.  The program can use this to
  478. //    determine whether or not pathName specifies a partial path.
  479. //----------------------------------------------------------------------------------------
  480.  
  481. FW_Boolean FW_CPrivFileSystemParser::WinGetDrivePath(const FW_CString& pathName,
  482.                                                     FW_CString& drivePath) 
  483. {
  484.     FW_CharacterPosition delimiterPosition;
  485.     FW_Boolean result = FALSE;
  486.  
  487.     drivePath = "";
  488.  
  489.     if (pathName.GetLength() > 0)
  490.     {
  491.         FW_CStringTool *tool = FW_CStringTool::GetCurrentStringTool();
  492.  
  493.         if (tool->FindCharacter(pathName, FW_kDriveDelimiter, delimiterPosition, pathName.GetLength() - 1, FW_kBackwards))
  494.         {
  495.             drivePath = pathName;
  496.             drivePath.Truncate(delimiterPosition + 1);
  497.             result = TRUE;
  498.         }
  499.     }
  500.  
  501.     return (result);
  502. }
  503. #endif
  504.  
  505.  
  506. #ifdef FW_BUILD_WIN
  507. //----------------------------------------------------------------------------------------
  508. //    FW_CPrivFileSystemParser::WinExpandPartialPath
  509. //
  510. //  Expands a partial pathName into a full pathName based on the current drive and
  511. //    directory.  
  512. //  On entry, pathName contains the partial pathname.  
  513. //  On exit, pathName contains the fully qualified pathname.
  514. //----------------------------------------------------------------------------------------
  515.  
  516. void FW_CPrivFileSystemParser::WinExpandPartialPath(FW_CString& pathName) 
  517. {
  518.     FW_CFileSystem::FileError theError = FW_CFileSystem::kNoError;
  519. FW_UNUSED(theError);
  520.  
  521. #ifdef FW_BUILD_WIN16
  522.     // [KVV] Instead of this tedious code, can use OpenFile(OF_PARSE…)
  523.  
  524.     if (IsPartialPath(pathName))
  525.     {
  526.         FW_CDynamicString drivePath;
  527.         FW_CDynamicString tempPathName;
  528.  
  529.         if (WinGetDrivePath(pathName, drivePath))
  530.         {
  531.             // PathNames of form c:dir\file.ext are being phased out.  Do not use.
  532.             FW_ASSERT(FALSE);
  533.         }
  534.         else
  535.         {
  536.             // Both these cases are built on top of the current directory or drive.
  537.             PrivGetWorkingDirectory(tempPathName);
  538.             
  539.             if ((pathName.GetLength() > 0) && (pathName[0] == FW_kPathDelimiter))
  540.             {
  541.                 // In this case, the path is in the form '\dir1\file.txt'
  542.                 //   So all we need to do is add the drive.
  543.                 WinGetDrivePath(tempPathName, drivePath);
  544.                 
  545.                 pathName.Prepend(drivePath);
  546.             }
  547.             else
  548.             {
  549.                 // In this case, the path is in the form 'dir1\file.txt'
  550.                 //   So we need to add the current working directory.
  551.                 if (pathName.GetLength() > 0)
  552.                 {
  553.                     AddDelimiter(tempPathName);
  554.                     tempPathName += pathName;
  555.                 }
  556.  
  557.                 pathName = tempPathName;
  558.             }
  559.         }
  560.     }
  561. #endif
  562.  
  563. #ifdef FW_BUILD_WIN32
  564.     // ??? This may or may not be a valid thing to do on Win32.  It needs to be verified.
  565.  
  566.     char* nameBuffer = new char[MAX_PATH];
  567.     char* filePortion;
  568.  
  569.     long bufferSize = ::GetFullPathName((const FW_Char*)pathName, MAX_PATH, nameBuffer, &filePortion);
  570.  
  571.     // Errors are getting eaten for now.  But I still want to see them when
  572.     //   debugging - jjw 8/12/93
  573.     if (bufferSize == 0)
  574.         theError = ::GetLastError();
  575.     else
  576.         pathName = nameBuffer;
  577.  
  578.     delete nameBuffer;
  579. #endif
  580. }
  581. #endif
  582.  
  583.  
  584. //===========================================
  585. // Macintosh Routines
  586. //===========================================
  587.  
  588. #ifdef FW_BUILD_MAC
  589. //----------------------------------------------------------------------------------------
  590. //    FW_CPrivFileSystemParser::MacGenerateFullPathName
  591. //
  592. //    Generate a pathname based on the vRefNum and dirID passed to the function.  Return
  593. //    TRUE if pathName contains a valid path including volume name.  If this routine 
  594. //    returns FALSE, the contents of pathName are undefined.  
  595. //----------------------------------------------------------------------------------------
  596.  
  597. OSErr FW_CPrivFileSystemParser::MacGenerateFullPathName(short vRefNum,
  598.                                                             long dirID,
  599.                                                             FW_CString& pathName) 
  600. {
  601.     CInfoPBRec paramBlock;
  602.     Str255 dirName = "\p";
  603.     OSErr theError = noErr;
  604.     FW_CDynamicString tempString;
  605.  
  606.     // Casts required for compilation.
  607.     paramBlock.dirInfo.ioNamePtr = (StringPtr) &dirName;
  608.     paramBlock.dirInfo.ioVRefNum = vRefNum;
  609.     paramBlock.dirInfo.ioDrParID = dirID;
  610.     paramBlock.dirInfo.ioFDirIndex = -1;
  611.  
  612.     do
  613.     {
  614.         paramBlock.dirInfo.ioDrDirID = paramBlock.dirInfo.ioDrParID;
  615.  
  616.         theError = ::PBGetCatInfoSync(¶mBlock);
  617.         if (theError != noErr)
  618.             return (theError);
  619.  
  620.         // Casts required for compilation.
  621.         tempString.ReplaceAll((FW_PascalChar*)&dirName);
  622.         tempString += ":";
  623.         tempString += pathName;
  624.         pathName = tempString;
  625.     } while (paramBlock.dirInfo.ioDrDirID != fsRtDirID);
  626.  
  627.     return (noErr);
  628. }
  629. #endif
  630.  
  631.  
  632. #ifdef FW_BUILD_MAC
  633. //----------------------------------------------------------------------------------------
  634. //    FW_CPrivFileSystemParser::MacGenerateDirectory
  635. //
  636. //    Get the name of the directory specified
  637. //----------------------------------------------------------------------------------------
  638.  
  639. OSErr FW_CPrivFileSystemParser::MacGenerateDirectory(short vRefNum,
  640.                                                          long dirID,
  641.                                                          FW_CDirectorySpecification& directory) 
  642. {
  643.     CInfoPBRec paramBlock;
  644.     Str255 dirName = "\p";
  645.     OSErr theError = noErr;
  646.     FSSpec theMacSpec;
  647.  
  648.     // Casts required for compilation.
  649.     paramBlock.dirInfo.ioNamePtr = (StringPtr) & dirName;
  650.     paramBlock.dirInfo.ioVRefNum = vRefNum;
  651.     paramBlock.dirInfo.ioDrParID = dirID;
  652.     paramBlock.dirInfo.ioFDirIndex = -1;
  653.  
  654.     paramBlock.dirInfo.ioDrDirID = paramBlock.dirInfo.ioDrParID;
  655.  
  656.     theError = ::PBGetCatInfoSync(¶mBlock);
  657.     if (theError != noErr)
  658.         return (theError);
  659.  
  660.     theError = ::FSMakeFSSpec(vRefNum, paramBlock.dirInfo.ioDrParID, dirName, &theMacSpec);
  661.  
  662.     if (theError != noErr)
  663.         return (theError);
  664.  
  665.     directory = theMacSpec;
  666.     return (noErr);
  667. }
  668. #endif
  669.  
  670.  
  671.